using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Xml;
using System.IO;
using WikiEngine;

namespace WikiLocal.Net
{
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	public class WikiLocalMainForm : System.Windows.Forms.Form
	{
        private Panel panel1;
        private ComboBox cbPage;
        private Button btnEdit;
        private Button btnGo;
        private SplitContainer scMain;
        private Label lblSidebarTitle;
        private Label lblPageTitle;
        private SplitContainer scPage;
        private SplitContainer scPageEdit;
        private Panel panel2;
        private Button btnCancel;
        private Button btnReset;
        private Button btnSave;
        private ListBox lbCommands;
        private WebBrowser wbSidebar;
        private TextBox txtEdit;
        private Label lblPageInfo;
        private WebBrowser wbPage;
        private ContextMenuStrip cmsSideBar;
        private ContextMenuStrip cmsRedirect;
        private ContextMenuStrip cmsPage;
        private StatusStrip statusStrip1;
        private ToolStripStatusLabel toolStripStatusLabel1;
        private ToolStripStatusLabel toolStripStatusLabel2;
        private ToolStripStatusLabel toolStripStatusLabel3;
        private IContainer components;

		public WikiLocalMainForm()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
            this.components = new System.ComponentModel.Container();
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(WikiLocalMainForm));
            this.panel1 = new System.Windows.Forms.Panel();
            this.cbPage = new System.Windows.Forms.ComboBox();
            this.btnGo = new System.Windows.Forms.Button();
            this.btnEdit = new System.Windows.Forms.Button();
            this.scMain = new System.Windows.Forms.SplitContainer();
            this.wbSidebar = new System.Windows.Forms.WebBrowser();
            this.lblSidebarTitle = new System.Windows.Forms.Label();
            this.cmsSideBar = new System.Windows.Forms.ContextMenuStrip(this.components);
            this.scPage = new System.Windows.Forms.SplitContainer();
            this.scPageEdit = new System.Windows.Forms.SplitContainer();
            this.txtEdit = new System.Windows.Forms.TextBox();
            this.lbCommands = new System.Windows.Forms.ListBox();
            this.panel2 = new System.Windows.Forms.Panel();
            this.btnCancel = new System.Windows.Forms.Button();
            this.btnReset = new System.Windows.Forms.Button();
            this.btnSave = new System.Windows.Forms.Button();
            this.wbPage = new System.Windows.Forms.WebBrowser();
            this.lblPageInfo = new System.Windows.Forms.Label();
            this.cmsRedirect = new System.Windows.Forms.ContextMenuStrip(this.components);
            this.lblPageTitle = new System.Windows.Forms.Label();
            this.cmsPage = new System.Windows.Forms.ContextMenuStrip(this.components);
            this.statusStrip1 = new System.Windows.Forms.StatusStrip();
            this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel();
            this.toolStripStatusLabel2 = new System.Windows.Forms.ToolStripStatusLabel();
            this.toolStripStatusLabel3 = new System.Windows.Forms.ToolStripStatusLabel();
            this.panel1.SuspendLayout();
            this.scMain.Panel1.SuspendLayout();
            this.scMain.Panel2.SuspendLayout();
            this.scMain.SuspendLayout();
            this.scPage.Panel1.SuspendLayout();
            this.scPage.Panel2.SuspendLayout();
            this.scPage.SuspendLayout();
            this.scPageEdit.Panel1.SuspendLayout();
            this.scPageEdit.Panel2.SuspendLayout();
            this.scPageEdit.SuspendLayout();
            this.panel2.SuspendLayout();
            this.statusStrip1.SuspendLayout();
            this.SuspendLayout();
            // 
            // panel1
            // 
            this.panel1.Controls.Add(this.cbPage);
            this.panel1.Controls.Add(this.btnGo);
            this.panel1.Controls.Add(this.btnEdit);
            this.panel1.Dock = System.Windows.Forms.DockStyle.Top;
            this.panel1.Location = new System.Drawing.Point(0, 0);
            this.panel1.Name = "panel1";
            this.panel1.Size = new System.Drawing.Size(566, 22);
            this.panel1.TabIndex = 0;
            // 
            // cbPage
            // 
            this.cbPage.Dock = System.Windows.Forms.DockStyle.Fill;
            this.cbPage.FormattingEnabled = true;
            this.cbPage.Location = new System.Drawing.Point(0, 0);
            this.cbPage.Name = "cbPage";
            this.cbPage.Size = new System.Drawing.Size(484, 24);
            this.cbPage.TabIndex = 2;
            this.cbPage.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.cbPage_MouseDoubleClick);
            this.cbPage.SelectedIndexChanged += new System.EventHandler(this.cbPage_SelectedIndexChanged);
            this.cbPage.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.cbPage_KeyPress);
            // 
            // btnGo
            // 
            this.btnGo.Dock = System.Windows.Forms.DockStyle.Right;
            this.btnGo.Location = new System.Drawing.Point(484, 0);
            this.btnGo.Name = "btnGo";
            this.btnGo.Size = new System.Drawing.Size(36, 22);
            this.btnGo.TabIndex = 0;
            this.btnGo.Text = "Go";
            this.btnGo.UseVisualStyleBackColor = true;
            this.btnGo.Click += new System.EventHandler(this.btnGo_Click);
            // 
            // btnEdit
            // 
            this.btnEdit.Dock = System.Windows.Forms.DockStyle.Right;
            this.btnEdit.Location = new System.Drawing.Point(520, 0);
            this.btnEdit.Name = "btnEdit";
            this.btnEdit.Size = new System.Drawing.Size(46, 22);
            this.btnEdit.TabIndex = 1;
            this.btnEdit.Text = "Edit";
            this.btnEdit.UseVisualStyleBackColor = true;
            this.btnEdit.Click += new System.EventHandler(this.btnEdit_Click);
            // 
            // scMain
            // 
            this.scMain.Dock = System.Windows.Forms.DockStyle.Fill;
            this.scMain.Location = new System.Drawing.Point(0, 22);
            this.scMain.Name = "scMain";
            // 
            // scMain.Panel1
            // 
            this.scMain.Panel1.Controls.Add(this.wbSidebar);
            this.scMain.Panel1.Controls.Add(this.lblSidebarTitle);
            // 
            // scMain.Panel2
            // 
            this.scMain.Panel2.Controls.Add(this.scPage);
            this.scMain.Size = new System.Drawing.Size(566, 355);
            this.scMain.SplitterDistance = 188;
            this.scMain.TabIndex = 1;
            // 
            // wbSidebar
            // 
            this.wbSidebar.Dock = System.Windows.Forms.DockStyle.Fill;
            this.wbSidebar.Location = new System.Drawing.Point(0, 32);
            this.wbSidebar.MinimumSize = new System.Drawing.Size(20, 20);
            this.wbSidebar.Name = "wbSidebar";
            this.wbSidebar.Size = new System.Drawing.Size(188, 323);
            this.wbSidebar.TabIndex = 1;
            this.wbSidebar.StatusTextChanged += new System.EventHandler(this.wbSidebar_StatusTextChanged);
            this.wbSidebar.Navigated += new System.Windows.Forms.WebBrowserNavigatedEventHandler(this.wbSidebar_Navigated);
            this.wbSidebar.Navigating += new System.Windows.Forms.WebBrowserNavigatingEventHandler(this.wbSidebar_Navigating);
            this.wbSidebar.NewWindow += new System.ComponentModel.CancelEventHandler(this.wbSidebar_NewWindow);
            // 
            // lblSidebarTitle
            // 
            this.lblSidebarTitle.BackColor = System.Drawing.SystemColors.InactiveCaption;
            this.lblSidebarTitle.ContextMenuStrip = this.cmsSideBar;
            this.lblSidebarTitle.Dock = System.Windows.Forms.DockStyle.Top;
            this.lblSidebarTitle.Font = new System.Drawing.Font("Verdana", 14F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.lblSidebarTitle.ForeColor = System.Drawing.SystemColors.InactiveCaptionText;
            this.lblSidebarTitle.Location = new System.Drawing.Point(0, 0);
            this.lblSidebarTitle.Name = "lblSidebarTitle";
            this.lblSidebarTitle.Padding = new System.Windows.Forms.Padding(4);
            this.lblSidebarTitle.Size = new System.Drawing.Size(188, 32);
            this.lblSidebarTitle.TabIndex = 0;
            this.lblSidebarTitle.Text = "Main";
            this.lblSidebarTitle.DoubleClick += new System.EventHandler(this.lblSidebarTitle_DoubleClick);
            this.lblSidebarTitle.Click += new System.EventHandler(this.lblSidebarTitle_Click);
            // 
            // cmsSideBar
            // 
            this.cmsSideBar.Name = "cmsSideBar";
            this.cmsSideBar.Size = new System.Drawing.Size(61, 4);
            // 
            // scPage
            // 
            this.scPage.Dock = System.Windows.Forms.DockStyle.Fill;
            this.scPage.Location = new System.Drawing.Point(0, 0);
            this.scPage.Name = "scPage";
            this.scPage.Orientation = System.Windows.Forms.Orientation.Horizontal;
            // 
            // scPage.Panel1
            // 
            this.scPage.Panel1.Controls.Add(this.scPageEdit);
            this.scPage.Panel1.Controls.Add(this.panel2);
            // 
            // scPage.Panel2
            // 
            this.scPage.Panel2.Controls.Add(this.wbPage);
            this.scPage.Panel2.Controls.Add(this.lblPageInfo);
            this.scPage.Panel2.Controls.Add(this.lblPageTitle);
            this.scPage.Size = new System.Drawing.Size(374, 355);
            this.scPage.SplitterDistance = 147;
            this.scPage.TabIndex = 1;
            // 
            // scPageEdit
            // 
            this.scPageEdit.Dock = System.Windows.Forms.DockStyle.Fill;
            this.scPageEdit.Location = new System.Drawing.Point(0, 0);
            this.scPageEdit.Name = "scPageEdit";
            // 
            // scPageEdit.Panel1
            // 
            this.scPageEdit.Panel1.Controls.Add(this.txtEdit);
            // 
            // scPageEdit.Panel2
            // 
            this.scPageEdit.Panel2.Controls.Add(this.lbCommands);
            this.scPageEdit.Size = new System.Drawing.Size(374, 124);
            this.scPageEdit.SplitterDistance = 191;
            this.scPageEdit.TabIndex = 1;
            // 
            // txtEdit
            // 
            this.txtEdit.Dock = System.Windows.Forms.DockStyle.Fill;
            this.txtEdit.HideSelection = false;
            this.txtEdit.Location = new System.Drawing.Point(0, 0);
            this.txtEdit.Multiline = true;
            this.txtEdit.Name = "txtEdit";
            this.txtEdit.ScrollBars = System.Windows.Forms.ScrollBars.Horizontal;
            this.txtEdit.Size = new System.Drawing.Size(191, 124);
            this.txtEdit.TabIndex = 0;
            this.txtEdit.TextChanged += new System.EventHandler(this.txtEdit_TextChanged);
            // 
            // lbCommands
            // 
            this.lbCommands.Dock = System.Windows.Forms.DockStyle.Fill;
            this.lbCommands.FormattingEnabled = true;
            this.lbCommands.ItemHeight = 16;
            this.lbCommands.Location = new System.Drawing.Point(0, 0);
            this.lbCommands.Name = "lbCommands";
            this.lbCommands.Size = new System.Drawing.Size(179, 116);
            this.lbCommands.TabIndex = 0;
            // 
            // panel2
            // 
            this.panel2.Controls.Add(this.btnCancel);
            this.panel2.Controls.Add(this.btnReset);
            this.panel2.Controls.Add(this.btnSave);
            this.panel2.Dock = System.Windows.Forms.DockStyle.Bottom;
            this.panel2.Location = new System.Drawing.Point(0, 124);
            this.panel2.Name = "panel2";
            this.panel2.Size = new System.Drawing.Size(374, 23);
            this.panel2.TabIndex = 0;
            // 
            // btnCancel
            // 
            this.btnCancel.Location = new System.Drawing.Point(156, 0);
            this.btnCancel.Name = "btnCancel";
            this.btnCancel.Size = new System.Drawing.Size(72, 23);
            this.btnCancel.TabIndex = 2;
            this.btnCancel.Text = "Cancel";
            this.btnCancel.UseVisualStyleBackColor = true;
            this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
            // 
            // btnReset
            // 
            this.btnReset.Location = new System.Drawing.Point(78, 0);
            this.btnReset.Name = "btnReset";
            this.btnReset.Size = new System.Drawing.Size(72, 23);
            this.btnReset.TabIndex = 1;
            this.btnReset.Text = "Reset";
            this.btnReset.UseVisualStyleBackColor = true;
            this.btnReset.Click += new System.EventHandler(this.btnReset_Click);
            // 
            // btnSave
            // 
            this.btnSave.Location = new System.Drawing.Point(0, 0);
            this.btnSave.Name = "btnSave";
            this.btnSave.Size = new System.Drawing.Size(72, 23);
            this.btnSave.TabIndex = 0;
            this.btnSave.Text = "Save";
            this.btnSave.UseVisualStyleBackColor = true;
            this.btnSave.Click += new System.EventHandler(this.btnSave_Click);
            // 
            // wbPage
            // 
            this.wbPage.Dock = System.Windows.Forms.DockStyle.Fill;
            this.wbPage.Location = new System.Drawing.Point(0, 53);
            this.wbPage.MinimumSize = new System.Drawing.Size(20, 20);
            this.wbPage.Name = "wbPage";
            this.wbPage.Size = new System.Drawing.Size(374, 151);
            this.wbPage.TabIndex = 1;
            this.wbPage.StatusTextChanged += new System.EventHandler(this.wbPage_StatusTextChanged);
            this.wbPage.Navigated += new System.Windows.Forms.WebBrowserNavigatedEventHandler(this.wbPage_Navigated);
            this.wbPage.Navigating += new System.Windows.Forms.WebBrowserNavigatingEventHandler(this.wbPage_Navigating);
            this.wbPage.NewWindow += new System.ComponentModel.CancelEventHandler(this.wbPage_NewWindow);
            // 
            // lblPageInfo
            // 
            this.lblPageInfo.BackColor = System.Drawing.SystemColors.Info;
            this.lblPageInfo.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.lblPageInfo.ContextMenuStrip = this.cmsRedirect;
            this.lblPageInfo.Dock = System.Windows.Forms.DockStyle.Top;
            this.lblPageInfo.ForeColor = System.Drawing.SystemColors.InfoText;
            this.lblPageInfo.Location = new System.Drawing.Point(0, 32);
            this.lblPageInfo.Name = "lblPageInfo";
            this.lblPageInfo.Padding = new System.Windows.Forms.Padding(1);
            this.lblPageInfo.Size = new System.Drawing.Size(374, 21);
            this.lblPageInfo.TabIndex = 2;
            this.lblPageInfo.Text = "page info...";
            this.lblPageInfo.Visible = false;
            // 
            // cmsRedirect
            // 
            this.cmsRedirect.Name = "cmsRedirect";
            this.cmsRedirect.Size = new System.Drawing.Size(61, 4);
            this.cmsRedirect.Opening += new System.ComponentModel.CancelEventHandler(this.cmsRedirect_Opening);
            // 
            // lblPageTitle
            // 
            this.lblPageTitle.BackColor = System.Drawing.SystemColors.ActiveCaption;
            this.lblPageTitle.ContextMenuStrip = this.cmsPage;
            this.lblPageTitle.Dock = System.Windows.Forms.DockStyle.Top;
            this.lblPageTitle.Font = new System.Drawing.Font("Verdana", 14F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.lblPageTitle.ForeColor = System.Drawing.SystemColors.ActiveCaptionText;
            this.lblPageTitle.Location = new System.Drawing.Point(0, 0);
            this.lblPageTitle.Name = "lblPageTitle";
            this.lblPageTitle.Padding = new System.Windows.Forms.Padding(4);
            this.lblPageTitle.Size = new System.Drawing.Size(374, 32);
            this.lblPageTitle.TabIndex = 0;
            this.lblPageTitle.Text = "Main.HomePage";
            this.lblPageTitle.DoubleClick += new System.EventHandler(this.lblPageTitle_DoubleClick);
            this.lblPageTitle.Click += new System.EventHandler(this.lblPageTitle_Click);
            // 
            // cmsPage
            // 
            this.cmsPage.Name = "cmsPage";
            this.cmsPage.Size = new System.Drawing.Size(61, 4);
            // 
            // statusStrip1
            // 
            this.statusStrip1.Font = new System.Drawing.Font("Verdana", 10F);
            this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.toolStripStatusLabel1,
            this.toolStripStatusLabel2,
            this.toolStripStatusLabel3});
            this.statusStrip1.Location = new System.Drawing.Point(0, 377);
            this.statusStrip1.Name = "statusStrip1";
            this.statusStrip1.Size = new System.Drawing.Size(566, 22);
            this.statusStrip1.TabIndex = 2;
            this.statusStrip1.Text = "statusStrip1";
            // 
            // toolStripStatusLabel1
            // 
            this.toolStripStatusLabel1.Name = "toolStripStatusLabel1";
            this.toolStripStatusLabel1.Size = new System.Drawing.Size(161, 17);
            this.toolStripStatusLabel1.Text = "...";
            // 
            // toolStripStatusLabel2
            // 
            this.toolStripStatusLabel2.Name = "toolStripStatusLabel2";
            this.toolStripStatusLabel2.Size = new System.Drawing.Size(161, 17);
            this.toolStripStatusLabel2.Text = "...";
            // 
            // toolStripStatusLabel3
            // 
            this.toolStripStatusLabel3.Name = "toolStripStatusLabel3";
            this.toolStripStatusLabel3.Size = new System.Drawing.Size(161, 17);
            this.toolStripStatusLabel3.Text = "...";
            // 
            // WikiLocalMainForm
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(7, 17);
            this.ClientSize = new System.Drawing.Size(566, 399);
            this.Controls.Add(this.scMain);
            this.Controls.Add(this.statusStrip1);
            this.Controls.Add(this.panel1);
            this.Font = new System.Drawing.Font("Verdana", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
            this.Name = "WikiLocalMainForm";
            this.StartPosition = System.Windows.Forms.FormStartPosition.WindowsDefaultBounds;
            this.Text = "WikiLocal";
            this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.WikiLocalMainForm_FormClosed);
            this.VisibleChanged += new System.EventHandler(this.WikiLocalMainForm_VisibleChanged);
            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.WikiLocalMainForm_FormClosing);
            this.Load += new System.EventHandler(this.WikiLocalMainForm_Load);
            this.panel1.ResumeLayout(false);
            this.scMain.Panel1.ResumeLayout(false);
            this.scMain.Panel2.ResumeLayout(false);
            this.scMain.ResumeLayout(false);
            this.scPage.Panel1.ResumeLayout(false);
            this.scPage.Panel2.ResumeLayout(false);
            this.scPage.ResumeLayout(false);
            this.scPageEdit.Panel1.ResumeLayout(false);
            this.scPageEdit.Panel1.PerformLayout();
            this.scPageEdit.Panel2.ResumeLayout(false);
            this.scPageEdit.ResumeLayout(false);
            this.panel2.ResumeLayout(false);
            this.statusStrip1.ResumeLayout(false);
            this.statusStrip1.PerformLayout();
            this.ResumeLayout(false);
            this.PerformLayout();

		}

		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main() 
		{
			Application.Run(new WikiLocalMainForm());
		}

		private void WikiLocalMainForm_Load(object sender, System.EventArgs e)
		{
			Application.ThreadException+=new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);

            //default view
            IsEditing = false;

            //load settings
            XmlDocument ini = GetIniXml();
            XmlElement iniBounds = ini.DocumentElement.SelectSingleNode("bounds") as XmlElement;
            if (iniBounds != null)
            {
                if (Convert.ToInt32(iniBounds.GetAttribute("maximized")) != 0)
                    WindowState = FormWindowState.Maximized;
                else
                    Bounds = XmlToRect(iniBounds);
                scMain.SplitterDistance = Convert.ToInt32(iniBounds.GetAttribute("sidebar"));
                scPage.SplitterDistance = Convert.ToInt32(iniBounds.GetAttribute("pageedit"));
                scPageEdit.SplitterDistance = Convert.ToInt32(iniBounds.GetAttribute("commands"));
            }
            //XmlElement iniWrap = ini.DocumentElement.SelectSingleNode("wrap") as XmlElement;
            //if (iniWrap != null) textBox1.WordWrap = Convert.ToBoolean(iniWrap.InnerText);
            ///TODO: wordwrap?

            string wikiDir = @".\WikiLocal";
            //TODO: applicationsetting?
            //TODO: optionally alternative path by parameter
            //expandpath?
            Storage = new WikiLocalStorage(wikiDir);

            //which WikiParseXML to load?

            //load WikiParseXml
            Engine.PageCheck = Storage;
            Engine.WikiParseXml = Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + "WikiLocal.xml";
            toolStripStatusLabel1.Text = Engine.WikiParseXmlLoadTime.ToString() + " ms";

            //set up flags, HTML is loaded on visible
            Application.Idle += new EventHandler(Application_Idle);
        }

        private bool wbPageAllowNav = false;
        private bool wbPageLoaded = false;
        private bool wbSidebarAllowNav = false;
        private bool wbSidebarLoaded = false;

        private bool SetEditing = false;

        private void WikiLocalMainForm_VisibleChanged(object sender, EventArgs e)
        {
            string WikiLocalHtml = "file://" + Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + "WikiLocal.html";
            wbPageAllowNav = true;
            wbPage.Navigate(WikiLocalHtml);
            wbSidebarAllowNav = true;
            wbSidebar.Navigate(WikiLocalHtml);
        }

        private void WikiLocalMainForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            XmlDocument ini = GetIniXml();
            XmlElement iniBounds = ForceElement(ini, "bounds");
            RectToXml(Bounds, iniBounds);
            iniBounds.SetAttribute("maximized", WindowState == FormWindowState.Maximized ? "1" : "0");
            iniBounds.SetAttribute("sidebar", scMain.SplitterDistance.ToString());
            iniBounds.SetAttribute("pageedit", scPage.SplitterDistance.ToString());
            iniBounds.SetAttribute("commands", scPageEdit.SplitterDistance.ToString());
            //ForceElement(ini, "wrap").InnerText = Convert.ToString(textBox1.WordWrap);
            ini.Save(IniPath);
        }

        void Application_Idle(object sender, EventArgs e)
        {
            if (DoMain && wbPageLoaded)
            {
                try
                {
                    HtmlElement body = wbPage.Document.Body;
                    float pre = body.ScrollRectangle.Height - body.ClientRectangle.Height == 0 ? -1 : body.ScrollTop / body.ScrollRectangle.Height - body.ClientRectangle.Height;

                    string pageData = "";
                    if (IsEditing)
                        pageData = txtEdit.Text;
                    else
                    {
                        if (Storage.GetPageData(ref WikiPage, WikiGroup, ref pageData))
                        {
                            cbPage.Items.Remove(WikiPage);
                            cbPage.Items.Insert(0, WikiPage);
                            cbPage.SelectedIndex = 0;
                        }
                        txtEdit.Text = pageData;
                        if (SetEditing) IsEditing = true;
                        if (WikiGroup != Storage.CurrentGroup)
                        {
                            DoSidebar = true;
                            WikiGroup = Storage.CurrentGroup;
                            WikiSideBarPage = WikiGroup + WikiGroupSeparator + WikiSideBar;
                        }
                    }
                    Storage.StoreLinks = IsEditing;
                    body.InnerHtml = Engine.Render(pageData);
                }
                catch (Exception ex)
                {
                    wbPage.Document.Body.InnerText = "ERROR " + ex.ToString();
                }
                toolStripStatusLabel2.Text = Engine.LastCallTime.ToString() + " ms";
                Storage.StoreLinks = false;
                lblPageTitle.Text = WikiPage;
                lbCommands.Items.Clear();
                foreach (WikiModification mod in Engine.Modifications)
                {
                    lbCommands.Items.Add(mod.Name + "=" + mod.Value);
                    //TODO redirect and others!
                }
                scPageEdit.Panel2Collapsed = Engine.Modifications.Count == 0;
                txtEdit.Modified = false;
                //TODO: use txtEdit.Modified
                DoMain = false;
            }
            if (DoSidebar && wbSidebarLoaded)
            {
                string sidebarName = WikiSideBarPage;
                try
                {
                    HtmlElement body = wbSidebar.Document.Body;
                    float pre = body.ScrollRectangle.Height - body.ClientRectangle.Height == 0 ? -1 : body.ScrollTop / body.ScrollRectangle.Height - body.ClientRectangle.Height;

                    string pageData = "";
                    Storage.GetPageData(ref sidebarName, WikiGroup, ref pageData);
                    //TODO: use return value?
                    body.InnerHtml = Engine.Render(pageData);
                }
                catch (Exception ex)
                {
                    wbSidebar.Document.Body.InnerText = "ERROR " + ex.ToString();
                }
                //TODO: redirects??
                lblSidebarTitle.Text = sidebarName;
                DoSidebar = false;
            }
        }

        private XmlDocument GetIniXml()
        {
            XmlDocument ini = new XmlDocument();
            if (File.Exists(IniPath)) ini.Load(IniPath); else ini.LoadXml("<settings />");
            return ini;
        }

        private Rectangle XmlToRect(XmlElement Element)
        {
            return new Rectangle(
                Convert.ToInt32(Element.GetAttribute("left")),
                Convert.ToInt32(Element.GetAttribute("top")),
                Convert.ToInt32(Element.GetAttribute("width")),
                Convert.ToInt32(Element.GetAttribute("height"))
                );
        }

        private void RectToXml(Rectangle Rect, XmlElement Element)
        {
            Element.SetAttribute("left", Rect.Left.ToString());
            Element.SetAttribute("top", Rect.Top.ToString());
            Element.SetAttribute("width", Rect.Width.ToString());
            Element.SetAttribute("height", Rect.Height.ToString());
        }

        private XmlElement ForceElement(XmlDocument doc, string NodeName)
        {
            XmlElement res = doc.DocumentElement.SelectSingleNode(NodeName) as XmlElement;
            //support advanced XPath?
            if (res == null)
            {
                res = doc.CreateElement(NodeName);
                doc.DocumentElement.AppendChild(res);
            }
            return res;
        }

        private void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
		{
			MessageBox.Show(this,e.Exception.ToString(),"Exception",MessageBoxButtons.OK,MessageBoxIcon.Error);
        }

        private const string WikiSideBar = "SideBar";
        private const string WikiHomePage = "HomePage";
        //storage needs these also!
        public const char WikiGroupSeparator = '.';
        public const string WikiDefaultGroup = "Main";

        private Engine Engine = new Engine();
        private WikiLocalStorage Storage;
        private string IniPath = Application.LocalUserAppDataPath + Path.DirectorySeparatorChar + "WikiLocal.ini";
        
        private bool DoMain = true;
        private bool DoSidebar = true;
        private string WikiGroup = WikiDefaultGroup;
        private string WikiSideBarPage = WikiDefaultGroup + WikiGroupSeparator + WikiSideBar;
        private string WikiPage = WikiDefaultGroup + WikiGroupSeparator + WikiHomePage;
        
        private void cbPage_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            cbPage.DroppedDown = true;
        }

        private void cbPage_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Return)
            {
                WikiPage = cbPage.Text;
                DoMain = true;
            }
        }

        private void lblSidebarTitle_Click(object sender, EventArgs e)
        {
            //TODO
        }

        private void lblPageTitle_DoubleClick(object sender, EventArgs e)
        {
            IsEditing = true;
        }

        private void cmsRedirect_Opening(object sender, CancelEventArgs e)
        {
            //TODO: 
        }

        private void btnGo_Click(object sender, EventArgs e)
        {
            WikiPage = cbPage.Text;
            DoMain = true;
        }

        private void wbSidebar_Navigating(object sender, WebBrowserNavigatingEventArgs e)
        {
            if (wbSidebarAllowNav)
            {
                wbSidebarAllowNav = false;
                wbSidebarLoaded = false;
            }
            else
            {
                e.Cancel = true;
                string url = e.Url.ToString();
                if (url.Substring(0, 12) == "wikilocal://")
                {
                    if (CheckEditing())
                    {
                        //if(url.Substring(12,6)=="/view/"
                        WikiPage = url.Substring(18);
                        DoMain = true;
                        if (url.Substring(12, 6) == "/edit/") SetEditing = true;
                    }
                    else
                        e.Cancel = false;
                }
                //TODO: open link
            }
        }

        private void wbPage_Navigating(object sender, WebBrowserNavigatingEventArgs e)
        {
            if (wbPageAllowNav)
            {
                wbPageAllowNav = false;
                wbPageLoaded = false;
            }
            else
            {
                e.Cancel = true;
                string url = e.Url.ToString();
                if (url.Substring(0, 12) == "wikilocal://")
                {
                    if (CheckEditing())
                    {
                        //if(url.Substring(12,6)=="/view/"
                        WikiPage = url.Substring(18);
                        DoMain = true;
                        if (url.Substring(12, 6) == "/edit/") SetEditing = true;
                    }
                    else
                        e.Cancel = false;
                }
                //TODO: open link
            }
        }

        private void wbSidebar_Navigated(object sender, WebBrowserNavigatedEventArgs e)
        {
            wbSidebarLoaded = true;
        }

        private void wbPage_Navigated(object sender, WebBrowserNavigatedEventArgs e)
        {
            wbPageLoaded = true;
            cbPage.Focus();
        }

        void wbSidebar_StatusTextChanged(object sender, EventArgs e)
        {
            toolStripStatusLabel3.Text = wbSidebar.StatusText;
        }

        void wbPage_StatusTextChanged(object sender, EventArgs e)
        {
            toolStripStatusLabel3.Text = wbPage.StatusText;
        }

        private void wbSidebar_NewWindow(object sender, CancelEventArgs e)
        {
            e.Cancel = true;
        }

        private void wbPage_NewWindow(object sender, CancelEventArgs e)
        {
            e.Cancel = true;
        }

        private bool IsEditing
        {
            set
            {
                SetEditing = false;
                scPage.Panel1Collapsed = !value;
                scPageEdit.Panel2Collapsed = !value && Engine.Modifications.Count == 0;
                if (value)
                {
                    txtEdit.Focus();
                    //TODO: selectall when getpagedata returned false
                }
                else
                {
                    //reload;
                    DoMain = true;
                    if (WikiPage == WikiSideBarPage) DoSidebar = true;
                }
            }
            get
            {
                return !scPage.Panel1Collapsed;
            }
        }

        private void btnEdit_Click(object sender, EventArgs e)
        {
            IsEditing = true;
        }

        private void Save()
        {
            Storage.SetPageData(WikiPage, txtEdit.Text);
            scPage.Panel1Collapsed = true;
            IsEditing = false;
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            Save();
        }

        private void txtEdit_TextChanged(object sender, EventArgs e)
        {
            DoMain = true;
        }

        private void lblPageTitle_Click(object sender, EventArgs e)
        {
            //
        }

        private bool CheckEditing()
        {
            if (IsEditing)
                switch (MessageBox.Show(this, "Save changes first?", "WikiLocal edit page", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question))
                {
                    case DialogResult.Yes:
                        Save();
                        return true;
                    case DialogResult.No:
                        IsEditing = false;
                        return true;
                    //case DialogResult.Cancel:
                    default:
                        return false;
                }
            else
                return true;
        }

        private void btnReset_Click(object sender, EventArgs e)
        {
            string pageData = "";
            Storage.GetPageData(ref WikiPage, WikiGroup, ref pageData);
            txtEdit.Text=pageData;
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            IsEditing = false;
        }

        private void WikiLocalMainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = !CheckEditing();
        }

        private void lblSidebarTitle_DoubleClick(object sender, EventArgs e)
        {
            if (CheckEditing())
            {
                WikiPage = WikiSideBarPage;
                DoMain = true;
                SetEditing = true;
            }
        }

        private void cbPage_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!DoMain && cbPage.SelectedIndex != -1 && CheckEditing())
            {
                WikiPage = cbPage.Text;
                DoMain = true;
            }
        }

    }
}
